// 使用 hdf5 库

#include <iostream>
#include "libs/hdf5_util.h"

const std::string FILE_PATH = "test.h5";
const std::string GROUP_NAME = "tian";
// 写数据
bool writeh5()
{
    // 创建文件
    hid_t file_id = h5::create_file_with_auto_flush(FILE_PATH);
    if (file_id < 0) {
        return false;
    }
    DECLARE_HDF5_RESOURCE_MANAGER(file_id);

    // 创建group
    if (!h5::is_abel_to_create_dataset(file_id, GROUP_NAME.c_str())) {
        return false;
    }
    hid_t group_id = h5::create_group_id(file_id, GROUP_NAME.c_str());
    CHECK_RESOURCE_ID_AND_RETURN(group_id, false);
    DECLARE_HDF5_RESOURCE_MANAGER(group_id);

    // 定义要存储的数据 （存一个二维数据）
    const int rank = 2;  // 二维数据
    hsize_t dims[rank] = {5, 2};  // 5行 2列
    std::vector<std::vector<int>> data = {
        {0, 1},
        {2, 3},
        {4, 5}, 
        {6, 7},
        {8, 9}
    };

    // 创建数据空间（描述数据集维度）
    hid_t dataspace_id = H5Screate_simple(rank, dims, nullptr);
    CHECK_RESOURCE_ID_AND_RETURN(dataspace_id, false);

    // 创建数据集属性列表（使用默认配置）
    hid_t dataset_plist = H5Pcreate(H5P_DATASET_CREATE);
    CHECK_RESOURCE_ID_AND_RETURN(dataset_plist, false);
    DECLARE_HDF5_RESOURCE_MANAGER(dataset_plist);

    // 创建数据集（名称为"data"）
    hid_t dataset_id = H5Dcreate2(
        group_id,          // 父组ID
        "data",            // 数据集名称
        H5T_NATIVE_INT,    // 数据类型（整数）
        dataspace_id,      // 数据空间ID
        H5P_DEFAULT,       // 链接属性列表
        dataset_plist,     // 数据集创建属性列表
        H5P_DEFAULT        // 数据集访问属性列表
    );
    CHECK_RESOURCE_ID_AND_RETURN(dataset_id, false);
    DECLARE_HDF5_RESOURCE_MANAGER(dataset_id);

    // 向数据集写入数据
    // 注意：HDF5写入需要扁平的内存布局，这里将二维vector转为一维数组
    std::vector<int> flat_data;
    for (const auto& row : data) {
        flat_data.insert(flat_data.end(), row.begin(), row.end());
    }
    herr_t write_status = H5Dwrite(
        dataset_id,
        H5T_NATIVE_INT,
        H5S_ALL,  // 内存数据空间（使用全部）
        H5S_ALL,  // 文件数据空间（使用全部）
        H5P_DEFAULT,
        flat_data.data()
    );
    if (write_status < 0) {
        std::cerr << "Failed to write data to dataset" << std::endl;
        return false;
    }

    // 为数据集添加属性（a_length=10）
    // 创建属性数据空间（标量，因为属性是单个值）
    hid_t attr_dataspace = H5Screate(H5S_SCALAR);
    CHECK_RESOURCE_ID_AND_RETURN(attr_dataspace, false);
    DECLARE_HDF5_RESOURCE_MANAGER(attr_dataspace);

    // 创建属性
    hid_t attr_id = H5Acreate2(
        dataset_id,        // 要附加属性的对象（数据集）
        "a_length",          // 属性名称
        H5T_NATIVE_INT,    // 属性数据类型（整数）
        attr_dataspace,    // 属性数据空间
        H5P_DEFAULT,       // 属性创建属性列表
        H5P_DEFAULT        // 属性访问属性列表
    );
    CHECK_RESOURCE_ID_AND_RETURN(attr_id, false);
    DECLARE_HDF5_RESOURCE_MANAGER(attr_id);

    // 写入属性值（a_length=10）
    int a_length_value = 10;
    herr_t attr_write_status = H5Awrite(attr_id, H5T_NATIVE_INT, &a_length_value);
    if (attr_write_status < 0) {
        std::cerr << "Failed to write attribute" << std::endl;
        return false;
    }

    return true;
}

// 读数据
void readh5()
{
    hid_t file_id = h5::open_file_without_file_locking(FILE_PATH);
    if (file_id < 0)
    {
       std::cout << "File open fail..." << std::endl; 
       return;
    }
    DECLARE_HDF5_RESOURCE_MANAGER(file_id);

    // 打开group
    hid_t group_id = H5Gopen(file_id, GROUP_NAME.c_str(), H5P_DEFAULT);
    if (group_id < 0)
    {
       std::cout << "Open group fail..." << std::endl; 
       return;
    }
    DECLARE_HDF5_RESOURCE_MANAGER(group_id);

    // 检查uri是否存在
    std::cout << "111 " << h5::is_link_exist(group_id,"data") << std::endl;

    // 打开数据集
    hid_t dataset_id = H5Dopen(file_id, "tian/data", H5P_DEFAULT);
    if (dataset_id < 0)
    {
       std::cout << "Open dataset fail..." << std::endl; 
       return;
    }
    DECLARE_HDF5_RESOURCE_MANAGER(dataset_id);

    // 读数据集属性
    int a_length=0;
    int res = h5::read_attribute(dataset_id, "a_length", a_length);
    std::cout << res << ", " << a_length << std::endl;

    // 获取数据集的数据空间
    hid_t dataset_space_id = H5Dget_space(dataset_id);
    if (dataset_space_id < 0)
    {
       std::cout << "Open dataset space fail..." << std::endl; 
       return;
    }
    DECLARE_HDF5_RESOURCE_MANAGER(dataset_space_id);

    // 获取数据的维度(秩)
    int dataset_rank = H5Sget_simple_extent_ndims(dataset_space_id);
    std::cout << "dataset_rank is: " << dataset_rank << std::endl;

    // 获取数据的形状
    hsize_t dataset_shape[dataset_rank];
    H5Sget_simple_extent_dims(dataset_space_id, dataset_shape, nullptr);
    std::cout << "dataset shape 0 is: " << dataset_shape[0] << std::endl;

    // 读取数据(取部分)
    // 定义要读取的区域（例如：从索引 0 开始，读取 3 行元素）
    hsize_t start[2] = {0, 0};       // 起始位置 第0行第0列
    hsize_t count[2] = {3, 2};       // 读取数量 3行2列 
    herr_t select_status = H5Sselect_hyperslab(
        dataset_space_id, 
        H5S_SELECT_SET, 
        start, 
        nullptr,   // 步长， 默认1
        count, 
        nullptr    // 块大小， 默认1
    );
    if (select_status < 0) {
        std::cerr << "Failed to select hyperslab" << std::endl;
        return;
    }

    // 创建内存数据空间（3行2列）
    hsize_t mem_dims[2] = {3, 2};
    hid_t mem_space_id = H5Screate_simple(2, mem_dims, nullptr);
    if (mem_space_id < 0) {
        std::cerr << "create mem_space fail" << std::endl;
        return;
    }
    DECLARE_HDF5_RESOURCE_MANAGER(mem_space_id);

    // 读取数据
    std::vector<int> read_data(3 * 2);  // 存储读取结果的缓冲区
    herr_t read_status = H5Dread(
        dataset_id,
        H5T_NATIVE_INT,
        mem_space_id,
        dataset_space_id,
        H5P_DEFAULT,
        read_data.data()
    );
    if (read_status < 0) {
        std::cerr << "Failed to read dataset" << std::endl;
        return;
    }

    // 6. 打印读取结果
    std::cout << "读取的前3行数据：" << std::endl;
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 2; ++j) {
            std::cout << read_data[i * 2 + j] << " ";
        }
        std::cout << std::endl;
    }

    
}

int main()
{
    writeh5();

    readh5();

    return 0;
}
